﻿using System;
using System.Threading;
using Ibp.Service.Entity.ODAEntity;
using OdaOperation.Core.Parameters;
using OdaOperation.Extends;
using Teigha.Core;
using Teigha.TD;

namespace OdaOperation.Core.Creators
{
    /// <summary>
    /// DoubleCitationCreator类继承自BaseCreator并实现了IReferenceCreator接口
    /// </summary>
    public class DoubleCitationCreator : BaseCreator, IReferenceCreator
    {
        private string m_blockName; // 块名称
        private DoubleCitationParameter m_parameter; // 参数

        /// <summary>
        /// 构造函数，接收一个数据库对象
        /// </summary>
        /// <param name="pDb"></param>
        public DoubleCitationCreator(OdDbDatabase pDb)
            : base(pDb)
        {
        }

        /// <summary>
        /// 创建DoubleCitationCreator对象的方法，接收DoubleCitationParameter参数
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public DoubleCitationCreator Create(DoubleCitationParameter parameter)
        {
            // 初始化默认字体样式
            TextStyleCreator.InitDefaultsFont(m_database);
            m_parameter = parameter;
            // 开始内存事务
            MemoryTransaction value = MemoryManager.GetMemoryManager().StartTransaction(Thread.CurrentThread.ManagedThreadId);
            try
            {
                Create(); // 调用私有的Create方法
            }
            catch (Exception)
            {
            }
            // 停止内存事务
            MemoryManager.GetMemoryManager().StopTransaction(value);
            return this;
        }

        /// <summary>
        /// 私有的Create方法，创建图元
        /// </summary>
        private void Create()
        {
            m_blockName = m_parameter.BlockName; // 设置块名称
                                                 // 创建块表记录
            OdDbBlockTableRecord odDbBlockTableRecord = BlockTableRecordCreator.CreateOdDbBlockTableRecord(m_database, m_blockName);
            // 创建LineCreator和CircleCreator对象
            LineCreator lineCreator = new LineCreator(m_database, odDbBlockTableRecord.objectId(), m_parameter.LayerName);
            CircleCreator circleCreator = new CircleCreator(m_database, odDbBlockTableRecord.objectId(), m_parameter.LayerName);
            // 获取或初始化文本样式
            OdDbObjectId textStyle = TextStyleCreator.GetFont(m_database, m_parameter.FontStyle) ?? TextStyleCreator.InitDefaultsFont(m_database);
            // 创建线条
            lineCreator.CreateLine(m_parameter.First.ToGePoint3D(), m_parameter.Seconds.ToGePoint3D());
            double w11 = 0.0;
            double w12 = 0.0;
            // 创建上部标签文本
            OdDbMText odDbMText = CreateText(odDbBlockTableRecord, textStyle, m_parameter.UpLabel, delegate (OdGeExtents3d odgeExtend)
            {
                double num6 = odgeExtend.maxPoint().y - odgeExtend.minPoint().y;
                w11 = odgeExtend.maxPoint().x - odgeExtend.minPoint().x;
                return new OdGePoint3d(m_parameter.Seconds.X + m_parameter.DisLeft, m_parameter.Seconds.Y + num6 + 0.1, 0.0);
            });
            // 创建下部标签文本
            OdDbMText odDbMText2 = CreateText(odDbBlockTableRecord, textStyle, m_parameter.DownLabel, delegate (OdGeExtents3d odgeExtend)
            {
                w12 = odgeExtend.maxPoint().x - odgeExtend.minPoint().x;
                return new OdGePoint3d(m_parameter.Seconds.X + m_parameter.DisLeft, m_parameter.Seconds.Y - 0.1, 0.0);
            });
            // 计算最大宽度
            double num = Math.Max(w11, w12);
            OdGePoint3d thiry = new OdGePoint3d(m_parameter.Seconds.X + m_parameter.DisLeft + num + m_parameter.DisRight, m_parameter.Seconds.Y, 0.0);
            // 创建线条
            lineCreator.CreateLine(thiry, m_parameter.Seconds.ToGePoint3D());
            if (!m_parameter.WithCircle)
            {
                return;
            }

            double upFontWidth = 0.0;
            bool isAutoCircle = m_parameter.CircleRadius < 0.0;
            // 创建上部代码文本
            OdDbMText upText = CreateText(odDbBlockTableRecord, textStyle, m_parameter.UpCode, delegate (OdGeExtents3d odgeExtend)
            {
                double num4 = odgeExtend.maxPoint().y - odgeExtend.minPoint().y;
                double num5 = (upFontWidth = odgeExtend.maxPoint().x - odgeExtend.minPoint().x);
                m_parameter.CircleRadius = (isAutoCircle ? (Math.Max(num5, num4 * 2.0) * 0.5 + m_parameter.FontSize * 0.5) : m_parameter.CircleRadius);
                return new OdGePoint3d(thiry.x + m_parameter.CircleRadius - num5 * 0.5, thiry.y + num4 + m_parameter.FontSize * 0.1, thiry.z);
            });
            // 创建下部代码文本
            OdDbMText odDbMText3 = CreateText(odDbBlockTableRecord, textStyle, m_parameter.DownCode, delegate (OdGeExtents3d odgeExtend)
            {
                double num2 = odgeExtend.maxPoint().y - odgeExtend.minPoint().y;
                double num3 = odgeExtend.maxPoint().x - odgeExtend.minPoint().x;
                if (num3 > upFontWidth)
                {
                    m_parameter.CircleRadius = (isAutoCircle ? (Math.Max(num3, num2 * 2.0) * 0.5 + m_parameter.FontSize * 0.5) : m_parameter.CircleRadius);
                    upText.setLocation(new OdGePoint3d(thiry.x + m_parameter.CircleRadius - upFontWidth * 0.5, upText.location().y, 0.0));
                }

                return new OdGePoint3d(thiry.x + m_parameter.CircleRadius - num3 * 0.5, thiry.y - m_parameter.FontSize * 0.1, thiry.z);
            });
            // 创建圆形
            circleCreator.CreateCircle(new OdGePoint3d(thiry).Add(new OdGeVector3d(m_parameter.CircleRadius, 0.0, 0.0)), m_parameter.CircleRadius);
            // 创建线条
            lineCreator.CreateLine(thiry, new OdGePoint3d(thiry).Add(new OdGeVector3d(m_parameter.CircleRadius * 2.0, 0.0, 0.0)));
        }

        /// <summary>
        /// 私有方法，创建文本
        /// </summary>
        /// <param name="blockTableRecord"></param>
        /// <param name="textStyle"></param>
        /// <param name="contents"></param>
        /// <param name="GetPoint"></param>
        /// <returns></returns>
        private OdDbMText CreateText(OdDbBlockTableRecord blockTableRecord, OdDbObjectId textStyle, string contents, Func<OdGeExtents3d, OdGePoint3d> GetPoint)
        {
            // 开始内存事务
            MemoryTransaction value = MemoryManager.GetMemoryManager().StartTransaction(Thread.CurrentThread.ManagedThreadId);
            OdDbMText odDbMText = OdDbMText.createObject();
            if (textStyle != null)
            {
                odDbMText.setTextStyle(textStyle); // 设置文本样式
            }

            odDbMText.setHeight(m_parameter.FontSize); // 设置文本高度
            odDbMText.setTextHeight(m_parameter.FontSize); // 设置文本高度
            odDbMText.setDatabaseDefaults(m_database); // 设置数据库默认值
            odDbMText.setContents(contents); // 设置文本内容
            OdDbObjectId odDbObjectId = blockTableRecord.appendOdDbEntity(odDbMText); // 将文本添加到块表记录中
                                                                                      // 停止内存事务
            MemoryManager.GetMemoryManager().StopTransaction(value);
            odDbMText = odDbObjectId.openObject(OpenMode.kForWrite) as OdDbMText;
            OdGeExtents3d odGeExtents3d = new OdGeExtents3d();
            odDbMText.getGeomExtents(odGeExtents3d); // 获取几何范围
            odDbMText.setLocation(GetPoint(odGeExtents3d)); // 设置文本位置
            odDbMText.setLayer(m_parameter.LayerName); // 设置文本图层
            return odDbMText;
        }

        /// <summary>
        /// 创建块引用的方法，接收位置、比例、旋转角度和镜像平面作为参数
        /// </summary>
        /// <param name="location"></param>
        /// <param name="odGeScale"></param>
        /// <param name="rotating"></param>
        /// <param name="mirrorPlane"></param>
        public void CreateBlockReference(DPoint location, OdGeScale3d odGeScale = null, double rotating = 0.0, OdGePlane mirrorPlane = null)
        {
            new BlockReferenceCreator(m_database, m_parameter.BlockName, m_layerName).Create(new OdGePoint3d(location.X, location.Y, location.Z), odGeScale, rotating, mirrorPlane);
        }

        /// <summary>
        /// 创建块引用的方法，接收位置、比例、旋转角度、镜像平面和参数集合作为参数
        /// </summary>
        /// <param name="location"></param>
        /// <param name="odGeScale"></param>
        /// <param name="rotating"></param>
        /// <param name="mirrorPlane"></param>
        /// <param name="paramters"></param>
        public void CreateBlockReference(OdGePoint3d location, OdGeScale3d odGeScale = null, double rotating = 0.0, OdGePlane mirrorPlane = null, ParameterSet paramters = null)
        {
            new BlockReferenceCreator(m_database, m_parameter.BlockName, m_layerName).Create(location, odGeScale, rotating, mirrorPlane, paramters);
        }

        /// <summary>
        /// 创建块引用的方法，接收ReferenceParameter参数
        /// </summary>
        /// <param name="paramter"></param>
        public void CreateBlockReference(ReferenceParameter paramter)
        {
            new BlockReferenceCreator(m_database, m_parameter.BlockName, paramter.LayerName).Create(paramter.Location.ToGePoint3D(), paramter.Scale, paramter.Rotating, paramter.MirrorPlane, paramter.Parameters);
        }

        /// <summary>
        /// 创建块引用的方法，接收图层名称、位置、比例、旋转角度、镜像平面和参数集合作为参数
        /// </summary>
        /// <param name="layerName"></param>
        /// <param name="location"></param>
        /// <param name="odGeScale"></param>
        /// <param name="rotating"></param>
        /// <param name="mirrorPlane"></param>
        /// <param name="paramters"></param>
        public void CreateBlockReference(string layerName, DPoint location, OdGeScale3d odGeScale = null, double rotating = 0.0, OdGePlane mirrorPlane = null, ParameterSet paramters = null)
        {
            new BlockReferenceCreator(m_database, m_parameter.BlockName, layerName).Create(location.ToGePoint3D(), odGeScale, rotating, mirrorPlane, paramters);
        }
    }

}